// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <pollux/functions/lib/string_encoding_utils.h>
#include <pollux/vector/vector_encoding.h>

namespace kumo::pollux::functions {
    namespace {
        /// Check if the input vector's buffers are single referenced
        bool hasSingleReferencedBuffers(const FlatVector<StringView> &vector) {
            for (auto &buffer: vector.stringBuffers()) {
                if (!buffer->unique()) {
                    return false;
                }
            }
            return true;
        };
    } // namespace

    bool prepareFlatResultsVector(
        VectorPtr &result,
        const SelectivityVector &rows,
        exec::EvalCtx &context,
        VectorPtr &argToReuse,
        const TypePtr &resultType) {
        POLLUX_CHECK(resultType->is_varbinary() || resultType->is_varchar());

        if (!result && BaseVector::is_vector_writable(argToReuse) &&
            argToReuse->is_flat_encoding() &&
            hasSingleReferencedBuffers(*argToReuse->as_flat_vector<StringView>())) {
            // Move input vector to result
            POLLUX_CHECK(
                VectorEncoding::isFlat(argToReuse.get()->encoding()) &&
                argToReuse.get()->type_kind() == resultType->kind());

            result = std::move(argToReuse);
            return true;
        }
        // This will allocate results if not allocated
        BaseVector::ensure_writable(rows, resultType, context.pool(), result);

        POLLUX_CHECK(VectorEncoding::isFlat(result->encoding()));
        return false;
    }

    /// Return the string encoding of a vector, if not set UTF8 is returned
    bool isAscii(BaseVector *vector, const SelectivityVector &rows) {
        if (auto simpleVector = vector->template as<SimpleVector<StringView> >()) {
            auto ascii = simpleVector->isAscii(rows);
            return ascii.has_value() && ascii.value();
        }
        POLLUX_UNREACHABLE();
        return false;
    };
} // namespace kumo::pollux::functions
